package com.qzw.security.service.service.impl;

import com.qzw.common.data.BaseMysqlDao;
import com.qzw.common.service.BaseServiceImpl;
import com.qzw.security.api.config.Config;
import com.qzw.security.api.dict.StatusDict;
import com.qzw.security.api.model.Menu;
import com.qzw.security.api.query.MenuQuery;
import com.qzw.security.api.service.IMenuService;
import com.qzw.security.service.dao.MenuDao;
import com.qzw.security.service.dao.RoleDao;
import com.qzw.security.service.dao.UserDao;
import com.qzw.security.service.entity.SysMenu;
import com.qzw.security.service.entity.SysPermission;
import com.qzw.security.service.entity.SysRole;
import com.qzw.security.service.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.transaction.Transactional;
import java.util.*;

/**
 * @author ：quziwei
 * @date ：Created in 2020/6/2 11:55 上午
 * @description：实现类
 */
@Service
public class MenuServiceImpl extends BaseServiceImpl<Menu, SysMenu,Integer, MenuQuery> implements IMenuService {
    @Autowired
    private MenuDao dao;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private UserDao userDao;

    @Override
    protected BaseMysqlDao<SysMenu, Integer> getDao() {
        return dao;
    }

    @Override
    protected SysMenu model2Entity(Menu model) {
        SysMenu sysMenu = null;
        if (!ObjectUtils.isEmpty(model)) {
            sysMenu = new SysMenu();
            sysMenu.setCreateTime(model.getCreateTime());
            sysMenu.setDescription(model.getDescription());
            sysMenu.setId(model.getId());
            sysMenu.setName(model.getName());
            sysMenu.setParentId(model.getParentId());
            sysMenu.setSort(model.getSort());
            sysMenu.setStatus(model.getStatus());
            sysMenu.setType(model.getType());
            sysMenu.setUrl(model.getUrl());
        }
        return sysMenu;
    }

    @Override
    protected Menu entity2model(SysMenu entity) {
        Menu menu = null;
        if (!ObjectUtils.isEmpty(entity)) {
            menu = new Menu();
            menu.setCreateTime(entity.getCreateTime());
            menu.setDescription(entity.getDescription());
            menu.setId(entity.getId());
            menu.setName(entity.getName());
            menu.setParentId(entity.getParentId());
            menu.setSort(entity.getSort());
            menu.setStatus(entity.getStatus());
            menu.setType(entity.getType());
            menu.setUrl(entity.getUrl());
        }
        return menu;
    }

    @Override
    public List<Menu> findMenusByRoleId(Integer roleId) {
        Optional<SysRole> sysRole = roleDao.findById(roleId);
        return entity2Model(sysRole.get().getMenus());
    }

    @Override
    @Transactional
    public Menu update(Menu model) {
        if (ObjectUtils.isEmpty(model.getId())) {
            model = add(model);
        } else {
            Optional<SysMenu> sysMenuOptional = dao.findById(model.getId());
            SysMenu sysMenu = sysMenuOptional.get();
            if (isNotEmpty(model.getStatus()))
                sysMenu.setStatus(model.getStatus());
            if (isNotEmpty(model.getName()))
                sysMenu.setName(model.getName());
            if (isNotEmpty(model.getDescription()))
                sysMenu.setDescription(model.getDescription());
            if (isNotEmpty(model.getSort()))
                sysMenu.setSort(model.getSort());
            if (isNotEmpty(model.getType()))
                sysMenu.setType(model.getType());
            if (isNotEmpty(model.getUrl()))
                sysMenu.setUrl(model.getUrl());
            model = entity2model(dao.save(sysMenu));
        }
        return model;
    }

    @Override
    @Transactional
    public void permissionEdit(Integer menuId, List<Integer> permissionIds) {
        Optional<SysMenu> sysMenu = dao.findById(menuId);
        Set<SysPermission> sysPermissions = new HashSet<>();
        sysMenu.get().setPermissions(sysPermissions);
        if (!CollectionUtils.isEmpty(permissionIds))
            for (Integer id : permissionIds) {
                SysPermission sysPermission = new SysPermission();
                sysPermission.setId(id);
                sysPermissions.add(sysPermission);
            }
        dao.save(sysMenu.get());
    }

    @Override
    public List<String> findAliases(Menu menu) {



        Optional<SysMenu> sysMenu = dao.findOne(Example.of(model2Entity(menu)))  ;
        List<String> userIds = new ArrayList<>();
        if (isNotEmpty(sysMenu)) {
            Set<SysRole> sysRoles = sysMenu.get().getRoles();
            for (SysRole sysRole : sysRoles) {
                Set<SysUser> sysUsers = sysRole.getUsers();
                for (SysUser sysUser : sysUsers) {
                    userIds.add(sysUser.getUsername());
                }
            }
        }
        return userIds;
    }

    @Override
    @Transactional
    public List<Menu> findMenusByUserId(Integer userId) {
        Optional<SysUser> user = userDao.findById(userId);
        Set<SysRole> roles = user.get().getRoles();
        Collection<SysMenu> menus = new HashSet<>();
        for (SysRole role : roles) {
            Set<SysMenu> menuSet = role.getMenus();
            for (SysMenu menu : menuSet) {
                if (menu.getStatus().equals(StatusDict.SUCCESS)) {
                    menus.add(menu);
                }
            }
        }
        return entity2Model(menus);
    }

    @Override
    public List<Menu> findMenusConfigByUserId(Integer userId) {
        Optional<SysUser> user = userDao.findById(userId);
        Set<SysRole> roles = user.get().getRoles();
        Collection<SysMenu> menus = new HashSet<>();
        for (SysRole role : roles) {
            if (role.getStatus().equals(StatusDict.SUCCESS)) {
                Set<SysMenu> menuSet = role.getMenus();
                for (SysMenu menu : menuSet) {
                    if (menu.getStatus().equals(StatusDict.SUCCESS)) {
                        addMenu(menu, menus);
                    }
                }
            }
        }
        return entity2Model(menus);
    }

    @Override
    @Transactional
    public Menu add(Menu model) {
        model = super.add(model);

        // 保存菜单之后还需要配置给系统管理员角色
        Optional<SysRole> sysRole = roleDao.findById(Config.SYSTEM_MANAGER_ROLE_ID);
        Set<SysMenu> menus = sysRole.get().getMenus();
        SysMenu sysMenu = new SysMenu();
        sysMenu.setId(model.getId());
        menus.add(sysMenu);
        roleDao.save(sysRole.get());
        return model;
    }

    @Override
    public void deleteById(Integer integer) {
        Optional<SysMenu> sysMenu = dao.findById(integer);
        for (SysRole sysRole : sysMenu.get().getRoles()) {
            sysRole.getMenus().remove(sysMenu);
            roleDao.save(sysRole);
        }
        super.deleteById(integer);
    }

    private void addMenu(SysMenu menu, Collection<SysMenu> menuSet) {
        menuSet.add(menu);
        if (!ObjectUtils.isEmpty(menu.getParentId())) {
            Optional<SysMenu> parent = dao.findById(menu.getParentId());
            addMenu(parent.get(), menuSet);
        }
    }
}
